package base.thread_demo.demo11;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.locks.ReentrantLock;

/**
 * 因synchronized 和 ReentrantLock..lock()竞争不到锁而进入阻塞队列等待的线程,是不允许被打断的(Thread..interrupt()方法无效果).
 * 如果想可以打断阻塞队列里面的等待的线程,那么可以使用Thread..lockInterruptibly().
 *
 *  t1线程分别使用 lock.lockInterruptibly() 和 lock.lock() 试试
 *
 *  lock.lockInterruptibly()是被动等待别的线程通过Thread..interrupt()来打断我,防止线程死锁,如果想要主动
 *  中断自身线程,防止线程死锁,那么请尝试使用ReentrantLock..tryLock()
 *
 */
public class ReentrantLockDemo03 {
    private static final Logger log = LoggerFactory.getLogger(ReentrantLockDemo03.class);

    public static void main(String[] args) throws InterruptedException {
        ReentrantLock lock = new ReentrantLock();

        Thread t1 = new Thread(()->{
            try {
                log.info("t1 尝试获取锁");
                // 如果没有竞争，那么t1就会获得到lock对象锁，如果有竞争就会进入lock对象的阻塞队列，
                // lock的阻塞队列中线程是可以被其他线程用interrupt打断。
                lock.lockInterruptibly();// 该API会让线程成为lock锁对象的持有者,如果没有竞争到锁,就进入lock锁对象阻塞队列中等待

                try {
                    log.info("{} 获得到lock，继续执行锁定任务操作...", Thread.currentThread().getName());
                }finally {
                    log.info("{} unlock", Thread.currentThread().getName());
                    lock.unlock();
                }
            } catch (Exception e) {
                log.info("{} 从阻塞队列里等待时被打断",Thread.currentThread().getName());
                return;
            }
        },"t1");

        log.info("main lock");
        lock.lock();// main线程先持有锁
        try {
            //t1线程进入lock阻塞队列，直到main休眠2s后打断了阻塞队列里的t1,
            // t1通过lock.lockInterruptibly()是可以在等待过程中被打断的,
            // 如果t1通过lock.lock(),那么t1在等待过程中是不能被打断的.
            t1.start();
            Thread.sleep(2000);
            t1.interrupt();
        }finally {
            // 这里为了演示main 持有lock,而没有对lock进行释放
            //log.info("main unlock");
            //lock.unlock();
        }
        log.info("t1 被打断?->{}",t1.isInterrupted());
    }


}
